/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.google.code.peersim.metrics;

import com.google.code.peersim.metrics.ProximityMetricIfc.MeasurableEntityIfc;
import peersim.config.Configuration;

/**
 * Concrete implementation of the {@link ProximityMetricIfc} based on the concept of
 * <i>Euclidean distance</i>.
 *
 * @author frusso
 * @version 0.1
 * @since 0.1
 */
public class EuclideanMetric implements ProximityMetricIfc<EuclideanMetric.EuclideanMetricMeasurableIfc> {

  /**
   * The constant returned for the {@link EuclideanMetric#toString()} method.
   */
  private static final String MNEMONIC_NAME = "Euclidean metric";

  /**
   * This constructor is required by the PeerSim runtime.
   * @see Configuration#getClass(java.lang.String)
   * @param s
   */
  public EuclideanMetric(String s) {
    super();
  }

  /**
   * Constructor for testing purposes.
   */
  public EuclideanMetric() {
    super();
  }

  /**
   * {@inheritDoc}
   */
  public double unsignedDistanceBetween(EuclideanMetricMeasurableIfc a, EuclideanMetricMeasurableIfc b) {
    return Math.abs(signedDistanceBetween(a, b));
  }

  /**
   * {@inheritDoc}
   */
  public double signedDistanceBetween(EuclideanMetricMeasurableIfc a, EuclideanMetricMeasurableIfc b) {
    return Math.sqrt(Math.pow(a.getX() - b.getX(), 2) + Math.pow(a.getY() - b.getY(), 2));
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return MNEMONIC_NAME;
  }

  /**
   * In order for an entity to be measured by means of {@link EuclideanMetric}, it must expose
   * a bidimensional coordinate. This interface defines the set of accessor methods the
   * {@link EuclideanMetric} class leverages on.
   *
   * @author frusso
   * @version 0.1
   * @since 0.1
   */
  public interface EuclideanMetricMeasurableIfc extends MeasurableEntityIfc {

    /**
     * Get the {@code X} coordinate.
     *
     * @return The {@code X} coordinate
     */
    public int getX();

    /**
     * Get the {@code Y} coordinate.
     *
     * @return The {@code Y} coordinate
     */
    public int getY();
  }
}